package com.neo.tiny.middle.file.service;

import cn.hutool.core.bean.BeanUtil;
import com.neo.tiny.admin.sysConfig.bean.Storage;
import com.neo.tiny.admin.sysConfig.bean.StorageClientConfig;
import com.neo.tiny.admin.sysConfig.interfaces.SysConfigService;
import com.neo.tiny.common.constant.FileConstants;
import com.neo.tiny.common.util.CharUtil;
import com.neo.tiny.middle.file.log.entity.SysFileRecordDO;
import com.neo.tiny.middle.file.log.service.SysFileRecordService;
import com.neo.tiny.middle.file.storage.AbstractStorageClient;
import com.neo.tiny.middle.file.storage.StorageClient;
import com.neo.tiny.middle.file.vo.FileUploadResVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Description:
 * @Author: yqz
 * @CreateDate: 2022/11/14 22:40
 */
@Service
@AllArgsConstructor
public class StorageService {


    private final SysConfigService configService;

    private final List<AbstractStorageClient> storages;

    private final SysFileRecordService fileRecordService;

    /**
     * 存储文件
     *
     * @param inputStream   文件输入流
     * @param contentLength 文件长度
     * @param contentType   文件类型
     * @param fileName      文件名
     * @return 文件存储路径
     */
    public FileUploadResVO store(InputStream inputStream, long contentLength,
                                 String contentType, String fileName) {

        String key = generateKey(fileName);
        String uri = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) + "/" + key;

        StorageClient storageClient = getStorageClient();

        storageClient.store(inputStream, contentLength, contentType, uri);

        FileUploadResVO vo = new FileUploadResVO();
        String url = storageClient.generateUrl(uri);

        SysFileRecordDO fileLog = new SysFileRecordDO();
        fileLog.setFileName(key);
        fileLog.setBucketName(storageClient.getClientConfig().getActiveStorage().getBucketName());
        fileLog.setOriginalFileName(fileName);
        fileLog.setFileType(contentType);
        fileLog.setFileSize(contentLength);
        fileLog.setPath(uri);
        fileRecordService.save(fileLog);

        vo.setBizId(fileLog.getId());
        vo.setUri(url);
        vo.setFileName(fileName);
        vo.setFileType(fileName.substring(fileName.lastIndexOf(".") + 1));

        return vo;
    }

    /**
     * 生成索引key，数据库
     *
     * @param fileName
     * @return
     */
    private String generateKey(String fileName) {
        int index = fileName.lastIndexOf('.');
        String suffix = fileName.substring(index);
        return CharUtil.getRandomString(20) + suffix;
    }


    /**
     * 获取当前存储器
     *
     * @return 存储器
     */
    public StorageClient getStorageClient() {
        StorageClientConfig storageConfig = configService.loadStoreConfig(FileConstants.STORAGE_CONFIG);

        Map<String, Storage> configMap = new HashMap<>();
        BeanUtil.copyProperties(storageConfig, configMap);

        Optional<Storage> storageOptional = configMap.values().stream()
                .filter(Objects::nonNull)
                .filter(Storage::getEnable).findFirst();
        if (storageOptional.isPresent()) {
            Storage storage = storageOptional.get();
            // 遍历所有存储实现类
            for (AbstractStorageClient storageClient : storages) {
                if (storageClient.support(storage.getName())) {
                    storageConfig.setActiveStorage(storage);
                    storageClient.setClientConfig(storageConfig);
                    return storageClient;
                }
            }
        }
        return null;
    }
}
